package com.woniuxy.project115.kaer.tenant.service.impl;

import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.woniuxy.project115.kaer.commons.util.MD5Util;
import com.woniuxy.project115.kaer.commons.util.SMSUtil;
import com.woniuxy.project115.kaer.tenant.entity.TenantInfo;
import com.woniuxy.project115.kaer.tenant.mapper.TenantInfoMapper;
import com.woniuxy.project115.kaer.tenant.param.RegisterTenantParam;
import com.woniuxy.project115.kaer.tenant.service.TenantInfoService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.woniuxy.project115.kaer.tenant.util.RedisKey;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author HuH
 * @since 2025年02月17日
 */
@Service
public class TenantInfoServiceImpl extends ServiceImpl<TenantInfoMapper, TenantInfo> implements TenantInfoService {
    @Resource
    private TenantInfoMapper tenantInfoMapper;

    @Resource
    private StringRedisTemplate stringRedisTemplate;

    @Override
    public void register(RegisterTenantParam param) throws Exception {
        //幂等性检查
        TenantInfo info = tenantInfoMapper.selectOne(
                new QueryWrapper<TenantInfo>()
                        .eq("phone", param.getPhone())
                        .or()
                        .eq("card_id", param.getCardId()));
        if (info != null) {
            if (info.getPhone().equals(param.getPhone())) {
                throw new Exception("该手机号已被注册");
            }
            if (info.getCardId().equals(param.getCardId())) {
                throw new Exception("该身份证号已被注册");
            }
        }

        //短信验证码校验
        if (!stringRedisTemplate.hasKey(RedisKey.REGISTER_CODE_PHONE(param.getPhone()))) {
            throw new Exception("验证码已失效");
        }
        if (!param.getCode().equals(stringRedisTemplate.opsForValue().get(RedisKey.REGISTER_CODE_PHONE(param.getPhone())))) {
            throw new Exception("验证码错误");
        }

        //新增商家信息数据
        TenantInfo tenantInfo = BeanUtil.toBean(param, TenantInfo.class);
        tenantInfo.setRegisterTime(LocalDateTime.now(ZoneId.of("Asia/Shanghai")))
                .setState(0)
                .setPassword(MD5Util.md5(tenantInfo.getPassword(), tenantInfo.getPhone()));
        tenantInfoMapper.insert(tenantInfo);
    }

    @Override
    public TenantInfo login(String phone, String password) throws Exception {
        TenantInfo tenantInfo = tenantInfoMapper.selectOne(
                new QueryWrapper<TenantInfo>().eq("phone", phone));
        if (tenantInfo == null) {
            throw new Exception("该手机号未注册");
        }
        if (!tenantInfo.getPassword().equals(MD5Util.md5(password, phone))) {
            throw new Exception("密码错误");
        }
        return tenantInfo;
    }

    @Override
    public void sendRegisterCode(String phone) throws Exception {
        //判断1min内是否发送过注册短信验证码
        if (stringRedisTemplate.hasKey(RedisKey.REGISTER_CODE_STATE(phone))) {
            throw new Exception("请求过于频繁，1分钟后再次尝试");
        }
        //判断当前手机号是否已注册，去重
        TenantInfo tenantInfo = tenantInfoMapper.selectOne(new QueryWrapper<TenantInfo>().eq("phone", phone));
        if (tenantInfo != null) {
            throw new Exception("该手机号已注册");
        }

        //调用SMSUtil发送短息
        String code = SMSUtil.sendCode(phone);
        //使用redis保存验证码
        stringRedisTemplate.opsForValue().set(RedisKey.REGISTER_CODE_PHONE(phone), code, 300, TimeUnit.SECONDS);
        stringRedisTemplate.opsForValue().set(RedisKey.REGISTER_CODE_STATE(phone), "", 60, TimeUnit.SECONDS);
    }

    @Override
    public void sendLoginCode(String phone) throws Exception {
        //判断1min内是否发送过登录短信验证码
        if (stringRedisTemplate.hasKey(RedisKey.LOGIN_CODE_STATE(phone))) {
            throw new Exception("请求过于频繁，1分钟后再次尝试");
        }
        //判断当前手机号是否已注册
        TenantInfo tenantInfo = tenantInfoMapper.selectOne(new QueryWrapper<TenantInfo>().eq("phone", phone));
        if (tenantInfo == null) {
            throw new Exception("该手机号未注册");
        }

        //调用SMSUtil发送短息
        String code = SMSUtil.sendCode(phone);
        //使用redis保存验证码
        stringRedisTemplate.opsForValue().set(RedisKey.LOGIN_CODE_PHONE(phone), code, 300, TimeUnit.SECONDS);
        stringRedisTemplate.opsForValue().set(RedisKey.LOGIN_CODE_STATE(phone), "", 60, TimeUnit.SECONDS);
    }

    @Override
    public TenantInfo phoneLogin(String phone, String code) throws Exception {
        //短信验证码校验
        if (!stringRedisTemplate.hasKey(RedisKey.LOGIN_CODE_PHONE(phone))) {
            throw new Exception("验证码已失效");
        }
        if (!code.equals(stringRedisTemplate.opsForValue().get(RedisKey.LOGIN_CODE_PHONE(phone)))) {
            throw new Exception("验证码错误");
        }

        TenantInfo tenantInfo = tenantInfoMapper.selectOne(new QueryWrapper<TenantInfo>().eq("phone", phone));
        return tenantInfo;
    }

    @Override
    public void updatePassword(Integer tenantInfoId, String oldPassword, String newPassword) throws Exception {
        TenantInfo tenantInfo = tenantInfoMapper.selectById(tenantInfoId);
        if (!tenantInfo.getPassword().equals(MD5Util.md5(oldPassword, tenantInfo.getPhone()))) {
            throw new Exception("旧密码错误");
        }
        tenantInfo.setPassword(MD5Util.md5(newPassword, tenantInfo.getPhone()));
        tenantInfoMapper.updateById(tenantInfo);
    }

    @Override
    public Integer getState(Integer tenantInfoId) throws Exception {
        return tenantInfoMapper.selectById(tenantInfoId).getState();
    }

    @Override
    public void updateState(Integer tenantInfoId, Integer state) throws Exception {
        TenantInfo tenantInfo = tenantInfoMapper.selectById(tenantInfoId);
        if (tenantInfo == null) {
            throw new Exception("该用户不存在");
        }
        if (state != 0 || state != 1) {
            throw new Exception("状态值错误");
        }
        tenantInfo.setState(state);
        tenantInfoMapper.updateById(tenantInfo);
    }

    @Override
    public List<TenantInfo> getTenantInfo() throws Exception {
        List<TenantInfo> list = tenantInfoMapper.selectList(null);
        for (TenantInfo tenantInfo : list) {
            tenantInfo.setPassword("");
        }
        return list;
    }

    @Override
    public TenantInfo getTenantInfoByToken(Integer tenantInfoId) throws Exception {
        return tenantInfoMapper.selectById(tenantInfoId);
    }


}
